
#include<easyx.h>
#include <graphics.h> 
#include <windows.h>
#include<stdio.h>
#include"链表.h"
#include<conio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<vector>
#include<algorithm>



using namespace std;


//图形窗口的大小
#define BGWEIGHT 600//宽
#define BGHEIGHT 800//高
//我方飞机的大小
#define myAirWEIGHT   70
#define myAirHEIGHT   70
//敌机的大小
#define enemyPlaneWEIGHT  40
#define enemyPlaneHEIGHT  40
//子弹大小
#define BulletWEIGHT  10
#define BulletHEIGHT  10

//最大关卡数
#define MAX_LEVEL 5
//技能冷却时间
#define SKILL_COOLDOWN 300




IMAGE img[6];//图片数组
Node myPlane;//我方飞机
LL myBullet;//我方子弹
LL enemyPlane;//敌方飞机
vector<Particle> particles;//粒子效果
vector<Item>items;//道具列表
vector<Star>stars;//星空背景
int isEnd;//判断游戏结束
int count1;//得分
int comboCount;//连击计数
DWORD lastHitTime;//最后命中时间
int currentLevel;//当前关卡
int enemySpeed[MAX_LEVEL] = { 3,4,5,6,7 };//各关卡敌机速度
int enemySpawnRate[MAX_LEVEL] = { 100,80,60,40,20 };//各关卡低级生成速率
int skillCooldown;//技能冷却时间
int skillEnergy;//技能能量
GameState gameState;//游戏状态

//初始化星空背景
void initStars() {
	stars.clear();
	stars.reserve(100);
	for (int i = 0; i < 100; i++) {
		stars.push_back({
			rand() % BGWEIGHT,//x
			rand() % BGHEIGHT,//y
			rand() % 3 + 1,//speed
			rand() % 105 + 150//brightness
			});
	}

}

//粒子爆炸效果
void addExplosion(int x, int y, int count, COLORREF color) {
	particles.reserve(particles.size() + count);
	for (int i = 0; i < count; i++) {
		particles.push_back({
			x,y,//位置
			rand() % 11 - 5,//x速度-5到5
			rand() % 11 - 5,//y速度-5到5
			rand() % 30 + 20,//生命周期20-50帧
			1 + rand() % 3,//粒子大小1-3
			color//颜色
			});
	}
}


//显示起始页面
void ShowStartMenu() {
	cleardevice();
	setbkcolor(BLACK);
	cleardevice();

	settextcolor(WHITE);
	settextstyle(36, 0, _T("宋体"));
	outtextxy(120, 150, _T("飞机大作战"));

	settextstyle(24, 0, _T("宋体"));
	outtextxy(150, 250, _T("按任意键开始游戏"));
	outtextxy(150, 300, _T("按ESC键退出"));
	FlushBatchDraw();
	ExMessage msg;

	// 使用Windows API检测按键
	while (true) {
		if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
			closegraph();
			exit(0);
		}

		// 检测任意键按下
		for (int i = 1; i < 256; i++) {  // 扫描所有虚拟键码
			if (i != VK_ESCAPE && GetAsyncKeyState(i) & 0x8000) {
				return;
			}
		}

		Sleep(10);
	}
}

//显示暂停菜单
void ShowPauseMenu() {
	settextstyle(36, 0, _T("宋体"));
	outtextxy(150, 200, _T("游戏暂停"));
	settextstyle(24, 0, _T("宋体"));
	outtextxy(150, 300, _T("按P继续游戏"));
	outtextxy(150, 350, _T("按ESC退出"));
	FlushBatchDraw();

	while (true) {
		if (_kbhit()) {
			int key = _getch();
			if (key == 'P' || key == 'p') {
				gameState = PLAYING;
				return;
			}
			else if (key == 27) {
				gameState = MENU;
				return;
			}
		}
		Sleep(10);
	}
}
void cleanup();
	

//显示游戏结束
void ShowGameOver() {
	cleardevice();
	while (_kbhit()) _getch();

	// 绘制结束界面
	cleardevice();
	setbkcolor(BLACK);
	cleardevice();
	settextstyle(36, 0, _T("宋体"));
	outtextxy(150, 200, _T("游戏结束"));

	TCHAR scoreText[50];
	wsprintf(scoreText, "最终得分: %d", count1);
	settextstyle(24, 0, _T("宋体"));
	outtextxy(150, 300, scoreText);

	outtextxy(120, 400, _T("按任意键返回主菜单"));
	outtextxy(150, 450, _T("按ESC键退出"));

	FlushBatchDraw();

	// 改进的输入检测
	bool waitingInput = true;
	while (waitingInput) {
		// 优先检测ESC键
		if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
			Sleep(200); // 防抖延时
			closegraph();
			exit(0);
		}

		// 检测任意键
		for (int i = 8; i <= 254; i++) { // 跳过鼠标键和系统键
			if (GetAsyncKeyState(i) & 0x8000) {
				waitingInput = false;
				gameState = MENU;
				break;
			}
		}
		Sleep(10);
	}
}


//初始化函数
void init() 
{
	//加载图片
	loadimage(&img[0], "airplane\\background.png", BGWEIGHT, BGHEIGHT);
	loadimage(&img[1], "airplane\\我方飞机.png", myAirWEIGHT, myAirHEIGHT);
	loadimage(&img[2], "airplane\\敌机.png", enemyPlaneWEIGHT, enemyPlaneHEIGHT);
	loadimage(&img[3], "airplane\\子弹.png", BulletWEIGHT, BulletHEIGHT);
	loadimage(&img[4], "airplane\\敌机fast.png", enemyPlaneWEIGHT, enemyPlaneHEIGHT);
	loadimage(&img[5], "airplane\\敌机heavy.png", enemyPlaneWEIGHT, enemyPlaneHEIGHT);

	myPlane.x = BGWEIGHT / 2 - myAirWEIGHT / 2;
	myPlane.y = BGHEIGHT - myAirHEIGHT - 10;
	myPlane.speed = 8;
	myPlane.next = NULL;

	myBullet.head = NULL;
	myBullet.end = NULL;

	enemyPlane.head = NULL;
	enemyPlane.end = NULL;

	srand((unsigned int)time(NULL));

	isEnd = 0;//isEnd=1时游戏结束
	count1 = 0;
	comboCount = 0;
	lastHitTime = 0;
	currentLevel = 1;
	skillCooldown = 0;
	skillEnergy = 0;

	particles.clear();
	particles.reserve(500);
	items.clear();
	items.reserve(20);
	initStars();
}

//绘制星空背景
void drawStars() {
	for (auto& s : stars) {
		int gray = 150 + s.brightness;
		setfillcolor(RGB(gray, gray, gray));

		int starSize = 1 + (s.brightness % 3);
		fillcircle(s.x, s.y, starSize);

		s.y += s.speed;
		if (s.y > BGHEIGHT) {
			s.y = 0;
			s.x = rand() % BGWEIGHT;
			s.brightness = rand() % 105 + 150;
		}
	}

}

void DrawMap()
{
	cleardevice();
	BeginBatchDraw();

	setbkcolor(BLACK);
	cleardevice();

	drawStars();
	putimage(0, 0, &img[0]);
	//绘制道具
	for (auto& item : items) {
		COLORREF color;
		switch (item.type) {
		case HEALTH: color = GREEN; break;
		case POWERUP: color = RED; break;
		case SHIELD: color = BLUE; break;
		case BOMB: color = YELLOW; break;
		}
		setfillcolor(color);
		fillrectangle(item.x, item.y, item.x + 20, item.y + 20);
		item.y += item.speed;
	}

	//绘制玩家飞机
	putimage(myPlane.x, myPlane.y, &img[1]);

	//绘制敌机
	for (Node* temp = enemyPlane.head; temp != NULL; temp = temp->next)
	{
		int imgIndex = 2;
		if (temp->type == FAST) imgIndex = 4;
		else if (temp->type == HEAVY) imgIndex = 5;
		putimage(temp->x, temp->y, &img[imgIndex]);
	}

	//绘制子弹
	for (Node* temp = myBullet.head; temp != NULL; temp = temp->next)
	{
		putimage(temp->x, temp->y, &img[3]);
	}

	//绘制粒子效果
	for (auto& p : particles) {
		setfillcolor(p.color);
		solidcircle(p.x, p.y, p.size);
		p.x += p.vx;
		p.y += p.vy;
		p.life--;
	}
	particles.erase(remove_if(particles.begin(), particles.end(),
		[](const Particle& p) { return p.life <= 0; }), particles.end());

	//绘制UI
	settextcolor(WHITE);
	setbkmode(TRANSPARENT);

	//得分显示
	TCHAR str1[30];
	wsprintf(str1, "当前得分：%d", count1);
	outtextxy(5, 5, str1);
	
	// 显示连击
	if (comboCount > 1) {
		TCHAR comboStr[20];
		wsprintf(comboStr, "连击 x%d", comboCount);
		outtextxy(10, 50, comboStr);
	}

	// 显示技能能量
	setfillcolor(RGB(50, 50, 50));
	fillrectangle(BGWEIGHT - 110, 10, BGWEIGHT - 10, 30);
	setfillcolor(RGB(0, 200, 0));
	fillrectangle(BGWEIGHT - 110, 10, BGWEIGHT - 110 + skillEnergy, 30);
	outtextxy(BGWEIGHT - 200, 10, _T("技能能量"));

	// 显示当前关卡
	TCHAR levelStr[20];
	wsprintf(levelStr, "关卡: %d/%d", currentLevel, MAX_LEVEL);
	outtextxy(BGWEIGHT - 200, 40, levelStr);

	EndBatchDraw();
}

//生成子弹
void creat_myBullet()
{
	Node* bullet = Node_init(myPlane.x + myAirWEIGHT / 2 - BulletWEIGHT / 2,
		myPlane.y, 10);
	LinkList_insert(&myBullet, bullet);
}



//移动函数
void move()
{
	//移动子弹
	for (Node* temp = myBullet.head; temp != NULL; temp = temp->next)
	{
		temp->y = temp->y - temp->speed;
	}
	//移动敌机
	for (Node* temp = enemyPlane.head; temp != NULL; temp = temp->next)
	{
		temp->y = temp->y + temp->speed;
	}

	//更新技能冷却
	if (skillCooldown > 0) skillCooldown--;
}


// 碰撞检测
bool checkCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
	return abs(x1 - x2) < (w1 + w2) / 2 && abs(y1 - y2) < (h1 + h2) / 2;
}

// 游戏逻辑更新
void update() {
	// 检测子弹与敌机碰撞
	Node* tempBullet = myBullet.head;
	while (tempBullet != NULL) {
		Node* nextBullet = tempBullet->next;
		bool bulletHit = false;

		Node* tempEnemy = enemyPlane.head;
		while (tempEnemy != NULL && !bulletHit) {
			Node* nextEnemy = tempEnemy->next;

			if (checkCollision(
				tempBullet->x + BulletWEIGHT / 2, tempBullet->y + BulletHEIGHT / 2, BulletWEIGHT, BulletHEIGHT,
				tempEnemy->x + enemyPlaneWEIGHT / 2, tempEnemy->y + enemyPlaneHEIGHT / 2, enemyPlaneWEIGHT, enemyPlaneHEIGHT)) {

				// 敌机受伤
				tempEnemy->health--;

				// 添加命中效果
				addExplosion(tempEnemy->x + enemyPlaneWEIGHT / 2,
					tempEnemy->y + enemyPlaneHEIGHT / 2,
					5, RGB(255, 255, 0));

				// 如果敌机被摧毁
				if (tempEnemy->health <= 0) {
					// 连击系统
					DWORD currentTime = GetTickCount();
					if (currentTime - lastHitTime < 1000) {
						comboCount++;
					}
					else {
						comboCount = 1;
					}
					lastHitTime = currentTime;

					// 分数计算
					int baseScore = 10;
					if (tempEnemy->type == FAST) baseScore = 15;
					else if (tempEnemy->type == HEAVY) baseScore = 20;
					else if (tempEnemy->type == BONUS) baseScore = 50;

					count1 += baseScore + (comboCount * 2);
					skillEnergy = min(100, skillEnergy + 5);

					// 概率掉落道具
					if (rand() % 10 == 0) {
						items.push_back({
							tempEnemy->x, tempEnemy->y,
							(ItemType)(rand() % 4),
							2
							});
					}

					// 添加爆炸效果
					addExplosion(tempEnemy->x + enemyPlaneWEIGHT / 2,
						tempEnemy->y + enemyPlaneHEIGHT / 2,
						15, RGB(255, 100, 0));

					Node_delete(&enemyPlane, tempEnemy);
				}

				Node_delete(&myBullet, tempBullet);
				bulletHit = true;
			}
			tempEnemy = nextEnemy;
		}
		tempBullet = nextBullet;
	}

	// 检测玩家与敌机碰撞
	for (Node* temp = enemyPlane.head; temp != NULL; temp = temp->next) {
		if (checkCollision(
			myPlane.x + myAirWEIGHT / 2, myPlane.y + myAirHEIGHT / 2, myAirWEIGHT, myAirHEIGHT,
			temp->x + enemyPlaneWEIGHT / 2, temp->y + enemyPlaneHEIGHT / 2, enemyPlaneWEIGHT, enemyPlaneHEIGHT)) {

			addExplosion(myPlane.x + myAirWEIGHT / 2,
				myPlane.y + myAirHEIGHT / 2,
				30, RGB(255, 0, 0));
			isEnd = 1;
			break;
		}
	}
	// 检测玩家与道具碰撞
	for (auto it = items.begin(); it != items.end(); ) {
		if (checkCollision(
			myPlane.x + myAirWEIGHT / 2, myPlane.y + myAirHEIGHT / 2, myAirWEIGHT, myAirHEIGHT,
			it->x + 10, it->y + 10, 20, 20)) {

			// 根据道具类型应用效果
			switch (it->type) {
			case HEALTH: /* 增加生命 */ break;
			case POWERUP: /* 增强火力 */ break;
			case SHIELD: /* 临时护盾 */ break;
			case BOMB: /* 全屏炸弹 */
				for (Node* temp = enemyPlane.head; temp != NULL; temp = temp->next) {
					count1 += 5;
				}
				LinkList_All(&enemyPlane);
				break;
			}

			it = items.erase(it);
		}
		else {
			++it;
		}
	}
	// 移除越界子弹
	tempBullet = myBullet.head;
	while (tempBullet != NULL) {
		Node* next = tempBullet->next;
		if (tempBullet->y < -BulletHEIGHT) {
			Node_delete(&myBullet, tempBullet);
		}
		tempBullet = next;
	}

	// 移除越界敌机
	Node* tempEnemy = enemyPlane.head;
	while (tempEnemy != NULL) {
		Node* next = tempEnemy->next;
		if (tempEnemy->y > BGHEIGHT) {
			Node_delete(&enemyPlane, tempEnemy);
		}
		tempEnemy = next;
	}
	// 移除越界道具
	items.erase(remove_if(items.begin(), items.end(),
		[](const Item& i) { return i.y > BGHEIGHT; }), items.end());

	// 关卡进度
	static int lastScore = 0;
	if (count1 - lastScore > 500 && currentLevel < MAX_LEVEL) {
		lastScore = count1;
		currentLevel++;

		// 关卡提升提示
		settextcolor(YELLOW);
		outtextxy(150, 50, _T("难度提升!"));
		FlushBatchDraw();
		Sleep(1000);
	}
}

// 生成敌机
void enemyPlane_create() {
	static int val = 0;
	if (val >= enemySpawnRate[currentLevel - 1]) {
		int type = rand() % 4;
		int speed = enemySpeed[currentLevel - 1];
		if (type == FAST) speed *= 1.5;

		Node* enemy = Node_init(rand() % (BGWEIGHT - enemyPlaneWEIGHT),
			-enemyPlaneHEIGHT,
			speed,
			type,
			(type == HEAVY) ? 3 : 1);
		LinkList_insert(&enemyPlane, enemy);
		val = 0;
	}
	val++;
}

// 使用技能
void useSkill() {
	if (skillEnergy >= 100 && skillCooldown == 0) {
		// 全屏清敌
		for (Node* temp = enemyPlane.head; temp != NULL; temp = temp->next) {
			addExplosion(temp->x + enemyPlaneWEIGHT / 2,
				temp->y + enemyPlaneHEIGHT / 2,
				10, RGB(255, 100, 0));
			count1 += 5;
		}
		LinkList_All(&enemyPlane);
		skillEnergy = 0;
		skillCooldown = SKILL_COOLDOWN;
	}
}
//处理玩家输入
void play() {
	if (GetAsyncKeyState('W') & 0x8000 || GetAsyncKeyState(VK_UP) & 0x8000) {
		if (myPlane.y >= 0) myPlane.y -= myPlane.speed;
	}
	if (GetAsyncKeyState('S') & 0x8000 || GetAsyncKeyState(VK_DOWN) & 0x8000) {
		if (myPlane.y <= BGHEIGHT - myAirHEIGHT) myPlane.y += myPlane.speed;
	}
	if (GetAsyncKeyState('A') & 0x8000 || GetAsyncKeyState(VK_LEFT) & 0x8000) {
		if (myPlane.x >= 0) myPlane.x -= myPlane.speed;
	}
	if (GetAsyncKeyState('D') & 0x8000 || GetAsyncKeyState(VK_RIGHT) & 0x8000) {
		if (myPlane.x <= BGWEIGHT - myAirWEIGHT) myPlane.x += myPlane.speed;
	}
	static int shootCooldown = 0;
	if (shootCooldown > 0) {
		shootCooldown--;
	}
	if ((GetAsyncKeyState(VK_SPACE) & 0x8000) && shootCooldown == 0) {
		creat_myBullet();
		shootCooldown = 5;  // 设置发射冷却时间（10帧）
	}

	// 仍然保留peekmessage处理ESC等按键
	if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
		static DWORD lastEscTime = 0;
		DWORD currentTime = GetTickCount();
		if (currentTime - lastEscTime > 200) { // 防抖
			gameState = PAUSED;
			lastEscTime = currentTime;
		}
	}

	// 技能释放
	if (GetAsyncKeyState('Q') & 0x8000) {
		useSkill();
	}

	// 暂停游戏
	if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
		gameState = PAUSED;
	}
}

//清理资源
void cleanup() {
	LinkList_All(&myBullet);
	LinkList_All(&enemyPlane);
	particles.clear();
	items.clear();
	stars.clear();
}

void start() {
	initgraph(BGWEIGHT, BGHEIGHT);
	gameState = MENU;
	
	//初始化

	while (true)
	{
		switch (gameState) {
		case MENU:
			ShowStartMenu();
			init();
			gameState = PLAYING;
			break;
		case PLAYING: {
			static DWORD lastTime = GetTickCount();
			DWORD currentTime = GetTickCount();
			float deltaTime = (currentTime - lastTime) / 1000.0f;
			lastTime = currentTime;
			play();
			move();
			update();
			DrawMap();
			enemyPlane_create();
			// 控制帧率
			if (deltaTime < 0.016f) { // ~60FPS
				Sleep((0.016f - deltaTime) * 1000);
			}

			// 检查游戏结束
			if (isEnd) {
				gameState = GAMEOVER;
			}
			break;
		}
		case PAUSED:
			ShowPauseMenu();
			break;
		case GAMEOVER:
			cleanup();
			ShowGameOver();
			break;
		}
	}

		
		closegraph();
	}
